package src

import (
	"bytes"
	"errors"
	"reflect"
	"strconv"
)

func Struct2Json(v interface{}) (string,error){
	//准备一个缓冲
	var b bytes.Buffer

	//将任意值转换为json并输出到缓冲区
	if err := writeAny(&b ,reflect.ValueOf(v));err == nil {
		return b.String(),nil
	}else {
		return "",nil
	}
}

func writeAny(buff *bytes.Buffer,value reflect.Value) error {

	switch value.Kind() {
	case reflect.String:
		//写入带有双引号括起来的字符串
		//"Teacher 1"
		buff.WriteString(strconv.Quote(value.String()))
	case reflect.Int:
		//"Age":25
		buff.WriteString(strconv.FormatInt(value.Int(),10))
	case reflect.Slice:
		//切片
		return writeSlice(buff,value)
	case reflect.Struct:
		return writeStruct(buff,value)
	default:
		//遇到不认识的，报错
		return errors.New("unsupport kind:"+value.Kind().String())
	}
	return nil
}

//切片序列化
func writeSlice(buff *bytes.Buffer,value reflect.Value) error {

	//[{"Name":"Stu001","Age":1},{"Name":"Stu002","Age":2},{"Name":"Stu003","Age":3}]
	//开始标记
	buff.WriteString("[")
	//中间的字符，遍历字符串
	for s := 0; s < value.Len(); s++ {
		sliceValue := value.Index(s)
		//写入每个切片元素
		writeAny(buff,sliceValue)
		//每个元素尾部写入逗号，最后一个字段不写
		if s<value.Len()-1 {
			buff.WriteString(",")
		}
	}
	//结束标记
	buff.WriteString("]")

	return nil
}

//结构体序列化
func writeStruct(buff *bytes.Buffer,value reflect.Value) error {
	valueType := value.Type()

	//{"Name":"Teacher 1","Age":25,"Students":
	//[{"Name":"Stu001","Age":1},{"Name":"Stu002","Age":2},{"Name":"Stu003","Age":3}]}
	buff.WriteString("{")

	for i := 0; i < value.NumField(); i++ {

		//获取每个字段值
		fieldValue := value.Field(i)
		//获取每个字段的类型
		fieldType := valueType.Field(i)
		//字段名左边"
		buff.WriteString("\"")
		//写入字段名
		buff.WriteString(fieldType.Name)
		//写入字段名右双引号和冒号
		buff.WriteString("\":")
		//写入字段值
		writeAny(buff,fieldValue)
		//除了最后一个，末尾加，
		if i<value.NumField()-1 {
			buff.WriteString(",")
		}
	}
	buff.WriteString("}")
	return nil
}